Author
Affiliation
Magnus Johansson
Published

March 27, 2023

Code
# recode response categories to numerics
df <- df %>% 
  mutate(across(starts_with("A2_"), ~ recode(.x,"'Stämmer inte'=0;
                    'Stämmer delvis'=1;
                    'Stämmer helt'=2",
                    as.factor = FALSE)
  ))
Code
# filter relevant variables, only respondents from 2015 and 2019 with complete response data
df.omit.na <- df %>% 
  filter(inars %in% c(2015,2019)) %>% 
  mutaterskurs = recode(arskurs,"1='Åk 7';2='Åk 9';3='Gy 2';9=NA;99=NA", as.factor = TRUE),
         Kön = recode(kon,"99=NA;9=NA;2='Flickor';1='Pojkar'", as.factor = T),
         Skolkommun = recode(skolkommun,"1='Enköping';2='Heby';3='Håbo';4='Knivsta';
                             5='Tierp';6='Uppsala';7='Älvkarleby';8='Östhammar'", as.factor = T)
         #across(everything(), ~na_if(., ""))
         ) %>% 
  select(starts_with("A2_"),Årskurs,Kön,Skolkommun) %>% 
  na.omit()

# create variables for analysis of Differential Item Functioning
dif.arskurs <- df.omit.na$Årskurs
dif.gender <- df.omit.na$Kön
dif.skolkommun <- df.omit.na$Skolkommun

df.omit.na$Årskurs <- NULL
df.omit.na$Kön <- NULL
df.omit.na$Skolkommun <- NULL

names(df.omit.na) <- itemlabels$itemnr

# define subscales
sdq.pro <- c("sdq1","sdq4","sdq9","sdq17","sdq20")
sdq.emo <- c("sdq3","sdq8","sdq13","sdq16","sdq24")
sdq.cps <- c("sdq5","sdq7","sdq12","sdq18","sdq22")
sdq.hyp <- c("sdq2","sdq10","sdq15","sdq21","sdq25")
sdq.pps <- c("sdq6","sdq11","sdq14","sdq19","sdq23")

1 Bakgrund

Det finns LHU-data på SDQ från 2015 och framåt. Vi plockar ut data från 2015 och 2019 för den initiala analysen.

Tre svarskategorier till varje fråga kodas om till:

  • ‘Stämmer inte’=0
  • ‘Stämmer delvis’=1
  • ‘Stämmer helt’=2

Fem frågor reverseras (får sina svarsskalor omvända) för att alla frågor ska vara “vända åt samma håll” inom respektive delskala. Det är frågor som ingår i de fyra problemskalorna.

Code
recoded.items <- c("sdq7","sdq11","sdq14","sdq21","sdq25")

df.omit.na <- df.omit.na %>% 
  mutate(across(all_of(recoded.items), ~ recode(.x,"2=0;1=1;0=2",
                    as.factor = FALSE)
  ))

SDQ består av 5 subskalor med 5 frågor vardera. Det finns även en summerad användning av fyra av subskalorna till en Total Problem Scale.

2 Demografiska data

Code
RIdemographics(dif.gender, "Kön")
RIdemographics(dif.arskurs, "Årskurs")
RIdemographics(dif.skolkommun, "Skolkommun")
Kön n Percent
Flickor 6221 50.5
Pojkar 6094 49.5
Årskurs n Percent
Åk 7 4543 36.9
Åk 9 4289 34.8
Gy 2 3483 28.3
Skolkommun n Percent
Älvkarleby 227 1.8
Enköping 1071 8.7
Håbo 880 7.1
Heby 402 3.3
Knivsta 587 4.8
Östhammar 783 6.4
Tierp 666 5.4
Uppsala 7699 62.5

3 Deskriptiva data

Code
RIallresp(df.omit.na)
Response category Number of responses Percent
0 138561 45.0
1 106161 34.5
2 63153 20.5

Totalt antal svar per svarskategori för alla items

3.1 Descriptives - item level

itemnr item
sdq1 Jag försöker vara vänlig mot andra. Jag bryr mig om deras känslor
sdq2 Jag är rastlös. Jag kan inte vara stilla länge
sdq3 Jag har ofta huvudvärk, ont i magen eller illamående
sdq4 Jag delar ofta med mig till andra (t ex godis, spel, pennor)
sdq5 Jag blir mycket arg och tappar ofta humöret
sdq6 Jag är ofta för mig själv. Jag gör oftast saker ensam
sdq7 Jag gör oftast som jag blir tillsagd
sdq8 Jag oroar mig mycket
sdq9 Jag är hjälpsam om någon är ledsen, upprörd eller känner sig dålig
sdq10 Jag har svårt att sitta stilla, jag vill jämt röra och vrida på mig
sdq11 Jag har en eller flera kompisar
sdq12 Jag slåss eller bråkar mycket. Jag kan tvinga andra att göra som jag vill
sdq13 Jag är ofta ledsen, nedstämd eller gråtfärdig
sdq14 Jämnåriga verkar gilla mig för det mesta
sdq15 Jag har svårt att koncentrera mig, jag är lättstörd
sdq16 Jag blir nervös i nya situationer. Jag blir lätt osäker
sdq17 Jag är snäll mot yngre barn
sdq18 Jag blir ofta anklagad för att ljuga eller fuska
sdq19 Andra barn eller ungdomar retar eller mobbar mig
sdq20 Jag ställer ofta upp och hjälper andra (föräldrar, lärare, andra barn)
sdq21 Jag tänker mig för innan jag gör olika saker
sdq22 Jag tar saker som inte tillhör mig, t ex från skolan eller andra ställen
sdq23 Jag kommer bättre överens med vuxna än med jämnåriga
sdq24 Jag är rädd för mycket, jag är lättskrämd
sdq25 Jag kan koncentrera mig, göra klart det jag arbetar med
Code
RItileplot(df.omit.na)

Code
RIbarstack(df.omit.na)

Code
RIbarplot(df.omit.na)

Vi kan se att vissa svarskategorier används relativt sällan. Det framgår tydligast med “stacked bars”. Items 1, 4, 9, 17 och 20 har väldigt få svar i lägsta svarskategorin, medan 11, 12, 18, 19 och 22 har få svar i deras högsta svarskategori.

4 TPS Rasch-analys

Vi börjar med att titta på Total Problem Scale (TPS), som kombinerar fyra av delskalorna, och sedan tar vi var och en av subskalorna.

Code
df.tps <- df.omit.na %>% 
  select(!any_of(sdq.pro))

20 av SDQs 25 items ingår i denna analys.

4.1 Tak/golv-effekt, rådata

Code
RIrawdist(df.tps)

The eRm package, which uses Conditional Maximum Likelihood (CML) estimation, will be used primarily. For this analysis, the Partial Credit Model will be used.

itemnr item
sdq2 Jag är rastlös. Jag kan inte vara stilla länge
sdq3 Jag har ofta huvudvärk, ont i magen eller illamående
sdq5 Jag blir mycket arg och tappar ofta humöret
sdq6 Jag är ofta för mig själv. Jag gör oftast saker ensam
sdq7 Jag gör oftast som jag blir tillsagd
sdq8 Jag oroar mig mycket
sdq10 Jag har svårt att sitta stilla, jag vill jämt röra och vrida på mig
sdq11 Jag har en eller flera kompisar
sdq12 Jag slåss eller bråkar mycket. Jag kan tvinga andra att göra som jag vill
sdq13 Jag är ofta ledsen, nedstämd eller gråtfärdig
sdq14 Jämnåriga verkar gilla mig för det mesta
sdq15 Jag har svårt att koncentrera mig, jag är lättstörd
sdq16 Jag blir nervös i nya situationer. Jag blir lätt osäker
sdq18 Jag blir ofta anklagad för att ljuga eller fuska
sdq19 Andra barn eller ungdomar retar eller mobbar mig
sdq21 Jag tänker mig för innan jag gör olika saker
sdq22 Jag tar saker som inte tillhör mig, t ex från skolan eller andra ställen
sdq23 Jag kommer bättre överens med vuxna än med jämnåriga
sdq24 Jag är rädd för mycket, jag är lättskrämd
sdq25 Jag kan koncentrera mig, göra klart det jag arbetar med
Code
RIitemfitPCM2(df.tps, 300, 32, 8)
OutfitMSQ InfitMSQ OutfitZSTD InfitZSTD
sdq2 0.904 0.912 -1.394 -1.18
sdq3 0.916 0.924 -0.921 -1.181
sdq5 0.804 0.83 -2.374 -2.616
sdq6 1.124 1.07 0.975 0.965
sdq7 1.169 1.132 1.942 1.799
sdq8 0.95 0.949 -0.431 -0.91
sdq10 0.91 0.926 -1.172 -1.054
sdq11 0.865 0.925 -0.453 -0.359
sdq12 0.756 0.85 -0.916 -0.807
sdq13 0.757 0.816 -2.348 -2.492
sdq14 1.023 1.018 0.278 0.257
sdq15 0.802 0.816 -2.919 -2.958
sdq16 1.018 1.008 0.124 0.178
sdq18 0.977 0.958 -0.012 -0.287
sdq19 0.809 0.866 -0.877 -0.797
sdq21 1.086 1.077 1.156 1.095
sdq22 1.122 0.96 0.3 -0.142
sdq23 1.262 1.181 2.96 2.53
sdq24 1.035 1.005 0.31 0.006
sdq25 0.866 0.875 -1.796 -1.865
Code
RIpcmPCA(df.tps)
PCA of Rasch model residuals
Eigenvalues
2.68
1.97
1.34
1.29
1.11
Code
RIresidcorr(df.tps, cutoff = 0.2)
sdq2 sdq3 sdq5 sdq6 sdq7 sdq8 sdq10 sdq11 sdq12 sdq13 sdq14 sdq15 sdq16 sdq18 sdq19 sdq21 sdq22 sdq23 sdq24 sdq25
sdq2
sdq3 -0.11
sdq5 0.06 0.01
sdq6 -0.23 -0.08 -0.12
sdq7 0.02 -0.16 -0.02 -0.16
sdq8 -0.18 0.17 -0.05 0.01 -0.26
sdq10 0.52 -0.12 0.04 -0.23 0 -0.2
sdq11 -0.16 -0.09 -0.11 0.16 -0.01 -0.07 -0.18
sdq12 0.02 -0.1 0.12 -0.08 0.07 -0.17 0.03 0.04
sdq13 -0.19 0.19 0.05 0.07 -0.2 0.3 -0.21 0.03 -0.1
sdq14 -0.19 -0.1 -0.12 0.1 0.02 -0.1 -0.19 0.23 -0.07 -0.06
sdq15 0.18 -0.04 0.03 -0.17 -0.07 -0.09 0.19 -0.17 -0.05 -0.09 -0.17
sdq16 -0.18 0.04 -0.11 0.04 -0.25 0.24 -0.18 -0.07 -0.19 0.11 -0.03 -0.02
sdq18 0.01 -0.13 0.02 -0.09 0.07 -0.21 0.03 -0.02 0.15 -0.17 -0.04 -0.05 -0.2
sdq19 -0.13 -0.04 -0.07 0.03 -0.08 -0.05 -0.11 0.14 0.09 0.04 0.07 -0.09 -0.08 0.11
sdq21 0.06 -0.15 0.03 -0.18 0.19 -0.26 0.04 -0.01 0.07 -0.21 0.01 -0.03 -0.21 0.07 -0.08
sdq22 -0.03 -0.11 -0.03 -0.05 0.05 -0.15 -0.03 0 0.2 -0.11 -0.06 -0.08 -0.13 0.12 0.06 0.02
sdq23 -0.18 -0.07 -0.13 0.16 -0.12 -0.04 -0.16 0.04 -0.05 -0.07 0.04 -0.14 -0.07 -0.06 0.03 -0.18 -0.02
sdq24 -0.16 0.02 -0.08 -0.04 -0.18 0.17 -0.15 -0.04 -0.12 0.11 -0.06 -0.1 0.19 -0.14 0 -0.16 -0.07 -0.05
sdq25 0.1 -0.07 -0.01 -0.19 0.1 -0.14 0.08 -0.05 -0.04 -0.09 -0.03 0.31 -0.09 -0.02 -0.11 0.12 -0.07 -0.21 -0.15
Note:
Relative cut-off value (highlighted in red) is 0.161, which is 0.2 above the average correlation.
Code
RIloadLoc(df.tps)

Code
plot(mirt.tps, type="trace")

Code
# increase fig-height above as needed, if you have many items
RItargeting(df.tps)

Code
RIitemHierarchy(df.tps)

Item fit har få och relativt små avvikelser. PCA visar ett eigenvalue över 2.0, vilket indikerar mer än en dimension i data, vilket residualkorrelationerna ger en tydligare bild av. Däremot visar inte figure med faktorladdningar på första residualkontrasten någon tydlig subklustring. Flera items har oordnade svarskategorier, det rör 11, 12, 18, 19 och 22.

Code
# vi dokumenterar vilka items som behöver omkodas här
tps.items.recode <- c("sdq11","sdq12","sdq18","sdq19","sdq22")

4.2 DIF-analys

4.2.1 Kön

itemnr item
sdq2 Jag är rastlös. Jag kan inte vara stilla länge
sdq3 Jag har ofta huvudvärk, ont i magen eller illamående
sdq5 Jag blir mycket arg och tappar ofta humöret
sdq6 Jag är ofta för mig själv. Jag gör oftast saker ensam
sdq7 Jag gör oftast som jag blir tillsagd
sdq8 Jag oroar mig mycket
sdq10 Jag har svårt att sitta stilla, jag vill jämt röra och vrida på mig
sdq11 Jag har en eller flera kompisar
sdq12 Jag slåss eller bråkar mycket. Jag kan tvinga andra att göra som jag vill
sdq13 Jag är ofta ledsen, nedstämd eller gråtfärdig
sdq14 Jämnåriga verkar gilla mig för det mesta
sdq15 Jag har svårt att koncentrera mig, jag är lättstörd
sdq16 Jag blir nervös i nya situationer. Jag blir lätt osäker
sdq18 Jag blir ofta anklagad för att ljuga eller fuska
sdq19 Andra barn eller ungdomar retar eller mobbar mig
sdq21 Jag tänker mig för innan jag gör olika saker
sdq22 Jag tar saker som inte tillhör mig, t ex från skolan eller andra ställen
sdq23 Jag kommer bättre överens med vuxna än med jämnåriga
sdq24 Jag är rädd för mycket, jag är lättskrämd
sdq25 Jag kan koncentrera mig, göra klart det jag arbetar med
Code
RIdifTable(df.tps, dif.gender)

Item 2 3 Mean location StDev MaxDiff
sdq2 -0.661 -0.886 -0.774 0.159 0.225
sdq3 -0.662 0.117 -0.272 0.551 0.779
sdq5 -0.226 -0.051 -0.139 0.124 0.175
sdq6 -0.046 -0.193 -0.119 0.104 0.148
sdq7 0.161 -0.277 -0.058 0.310 0.438
sdq8 -1.242 -0.340 -0.791 0.638 0.902
sdq10 -0.536 -0.870 -0.703 0.236 0.334
sdq11 1.346 1.192 1.269 0.109 0.154
sdq12 1.540 0.964 1.252 0.407 0.576
sdq13 -0.314 0.557 0.122 0.616 0.871
sdq14 0.308 0.189 0.249 0.084 0.119
sdq15 -0.843 -0.832 -0.838 0.008 0.012
sdq16 -1.297 -0.663 -0.980 0.448 0.634
sdq18 0.943 0.168 0.555 0.548 0.775
sdq19 1.197 0.934 1.066 0.186 0.263
sdq21 0.047 -0.426 -0.189 0.335 0.473
sdq22 1.125 0.694 0.909 0.304 0.430
sdq23 -0.201 -0.474 -0.338 0.193 0.273
sdq24 -0.243 0.585 0.171 0.585 0.828
sdq25 -0.397 -0.388 -0.392 0.006 0.009
Code
RIdifFigure(df.tps, dif.gender)

Code
RIdifFigThresh(df.tps, dif.gender)

7 items uppvisar problem med DIF för kön över gränsvärdet 0.5, och ytterligare tre items är över 0.4.

4.2.2 Årskurs

itemnr item
sdq2 Jag är rastlös. Jag kan inte vara stilla länge
sdq3 Jag har ofta huvudvärk, ont i magen eller illamående
sdq5 Jag blir mycket arg och tappar ofta humöret
sdq6 Jag är ofta för mig själv. Jag gör oftast saker ensam
sdq7 Jag gör oftast som jag blir tillsagd
sdq8 Jag oroar mig mycket
sdq10 Jag har svårt att sitta stilla, jag vill jämt röra och vrida på mig
sdq11 Jag har en eller flera kompisar
sdq12 Jag slåss eller bråkar mycket. Jag kan tvinga andra att göra som jag vill
sdq13 Jag är ofta ledsen, nedstämd eller gråtfärdig
sdq14 Jämnåriga verkar gilla mig för det mesta
sdq15 Jag har svårt att koncentrera mig, jag är lättstörd
sdq16 Jag blir nervös i nya situationer. Jag blir lätt osäker
sdq18 Jag blir ofta anklagad för att ljuga eller fuska
sdq19 Andra barn eller ungdomar retar eller mobbar mig
sdq21 Jag tänker mig för innan jag gör olika saker
sdq22 Jag tar saker som inte tillhör mig, t ex från skolan eller andra ställen
sdq23 Jag kommer bättre överens med vuxna än med jämnåriga
sdq24 Jag är rädd för mycket, jag är lättskrämd
sdq25 Jag kan koncentrera mig, göra klart det jag arbetar med
Code
RIdifTable(df.tps, dif.arskurs)

Item 3 4 5 Mean location StDev MaxDiff
sdq2 -0.699 -0.722 -0.875 -0.765 0.096 0.176
sdq3 -0.241 -0.265 -0.442 -0.316 0.110 0.201
sdq5 -0.186 -0.153 -0.043 -0.127 0.075 0.142
sdq6 0.005 -0.103 -0.255 -0.118 0.131 0.260
sdq7 -0.130 -0.026 0.061 -0.032 0.096 0.191
sdq8 -0.534 -0.825 -1.092 -0.817 0.279 0.557
sdq10 -0.744 -0.608 -0.709 -0.687 0.071 0.136
sdq11 1.238 1.197 1.447 1.294 0.134 0.250
sdq12 1.282 1.186 1.255 1.241 0.050 0.096
sdq13 0.116 0.091 -0.072 0.045 0.102 0.188
sdq14 0.152 0.230 0.452 0.278 0.155 0.300
sdq15 -0.727 -0.795 -0.980 -0.834 0.131 0.252
sdq16 -0.887 -0.984 -1.089 -0.987 0.101 0.202
sdq18 0.358 0.498 0.859 0.572 0.259 0.501
sdq19 0.857 1.116 1.363 1.112 0.253 0.506
sdq21 -0.331 -0.179 0.026 -0.161 0.179 0.357
sdq22 0.870 0.910 0.975 0.918 0.053 0.105
sdq23 -0.137 -0.342 -0.519 -0.333 0.191 0.382
sdq24 -0.001 0.148 0.183 0.110 0.098 0.184
sdq25 -0.260 -0.372 -0.544 -0.392 0.143 0.285
Code
RIdifFigure(df.tps, dif.arskurs)

Code
RIdifFigThresh(df.tps, dif.arskurs)

Tre items går över gränsvärdet gällande årskurs.

4.2.3 Interaktion mellan kön och årskurs

Code
dfin <- df.tps

df.tree <- data.frame(matrix(ncol = 0, nrow = nrow(dfin)))
df.tree$difdata <- as.matrix(dfin)
df.tree$dif.gender <- dif.gender
df.tree$dif.arskurs <- dif.arskurs

pctree.out <- pctree(difdata ~ dif.gender + dif.arskurs, data = df.tree)
plot(pctree.out)

Code
cutoff <- 0.5
itempar(pctree.out) %>%
  as.data.frame() %>%
  t() %>%
  as.data.frame() %>%
  mutate(
    `Mean location` = rowMeans(.),
    StDev = rowSds(as.matrix(.))
  ) %>%
  rowwise() %>%
  mutate(MaxDiff = (max(c_across(c(1:(ncol(.) - 2))))) -
    min(c_across(c(1:(ncol(.) - 2))))) %>%
  ungroup() %>%
  mutate(across(where(is.numeric), round, 3)) %>%
  rownames_to_column(var = "Item") %>%
  mutate(Item = names(dfin)) %>%
  relocate(MaxDiff, .after = last_col()) %>%
  formattable(
    list(MaxDiff = formatter("span",
      style = ~ style(color = ifelse(MaxDiff < -cutoff,
        "red", ifelse(MaxDiff > cutoff, "red", "black")
      ))
    )),
    table.attr = "class=\"table table-striped\" style=\"font-size: 15px; font-family: Lato\""
  )
Item 3 5 6 9 10 11 Mean location StDev MaxDiff
sdq2 -0.582 -0.618 -0.846 -0.859 -0.872 -0.959 -0.789 0.152 0.377
sdq3 -0.551 -0.629 -0.859 0.142 0.155 0.036 -0.284 0.447 1.015
sdq5 -0.288 -0.227 -0.169 -0.093 -0.104 0.059 -0.137 0.121 0.347
sdq6 0.008 -0.062 -0.127 -0.022 -0.180 -0.429 -0.135 0.159 0.437
sdq7 0.005 0.162 0.395 -0.310 -0.255 -0.280 -0.047 0.286 0.705
sdq8 -0.926 -1.334 -1.621 -0.097 -0.328 -0.647 -0.826 0.585 1.524
sdq10 -0.602 -0.431 -0.606 -0.932 -0.827 -0.864 -0.710 0.193 0.501
sdq11 1.300 1.240 1.592 1.161 1.148 1.294 1.289 0.162 0.444
sdq12 1.616 1.415 1.642 0.985 0.954 0.950 1.261 0.335 0.692
sdq13 -0.226 -0.271 -0.506 0.595 0.552 0.509 0.109 0.495 1.101
sdq14 0.204 0.258 0.495 0.065 0.172 0.372 0.261 0.153 0.430
sdq15 -0.752 -0.784 -1.060 -0.743 -0.853 -0.940 -0.855 0.124 0.317
sdq16 -1.221 -1.329 -1.379 -0.558 -0.649 -0.826 -0.994 0.360 0.821
sdq18 0.683 1.016 1.264 0.034 0.068 0.511 0.596 0.496 1.230
sdq19 0.901 1.291 1.619 0.794 0.933 1.130 1.111 0.306 0.825
sdq21 -0.117 0.117 0.165 -0.583 -0.486 -0.151 -0.176 0.306 0.747
sdq22 1.120 1.093 1.164 0.616 0.708 0.772 0.912 0.240 0.548
sdq23 0.030 -0.303 -0.383 -0.346 -0.421 -0.704 -0.355 0.236 0.734
sdq24 -0.329 -0.219 -0.184 0.421 0.672 0.700 0.177 0.473 1.028
sdq25 -0.272 -0.387 -0.595 -0.271 -0.389 -0.534 -0.408 0.133 0.324

Minst 13 items har problem.

5 Delskalorna i SDQ

Vi börjar med den prosociala delskalan, eftersom den inte var med i Total Problem Score.

5.1 Prosocial delskala

Code
df.pro <- df.omit.na %>% 
  select(any_of(sdq.pro))
itemnr item
sdq1 Jag försöker vara vänlig mot andra. Jag bryr mig om deras känslor
sdq4 Jag delar ofta med mig till andra (t ex godis, spel, pennor)
sdq9 Jag är hjälpsam om någon är ledsen, upprörd eller känner sig dålig
sdq17 Jag är snäll mot yngre barn
sdq20 Jag ställer ofta upp och hjälper andra (föräldrar, lärare, andra barn)
Code
RIitemfitPCM2(df.pro, 300, 32, 8)
OutfitMSQ InfitMSQ OutfitZSTD InfitZSTD
sdq1 0.8 0.806 -1.425 -2.029
sdq4 1.036 1.026 0.35 0.192
sdq9 0.761 0.763 -2.982 -2.877
sdq17 0.857 0.837 -0.814 -1.643
sdq20 0.811 0.812 -2.534 -2.478
Code
RIpcmPCA(df.pro)
PCA of Rasch model residuals
Eigenvalues
1.40
1.28
1.23
1.07
0.02
Code
RIresidcorr(df.pro, cutoff = 0.2)
sdq1 sdq4 sdq9 sdq17 sdq20
sdq1
sdq4 -0.25
sdq9 -0.05 -0.24
sdq17 -0.07 -0.26 -0.18
sdq20 -0.16 -0.21 -0.09 -0.15
Note:
Relative cut-off value (highlighted in red) is 0.034, which is 0.2 above the average correlation.
Code
RIloadLoc(df.pro)

Code
plot(mirt.rasch, type="trace")

Code
# increase fig-height above as needed, if you have many items
RItargeting(df.pro)

Code
RIitemHierarchy(df.pro)

Förutom något låg item fit för några items finns inga problem med dimensionalitet. Däremot är targeting dålig, och en tydlig takeffekt finns.

5.1.1 Reliabilitet

Code
RItif(df.pro)

Reliabiliteten är mycket låg.

5.1.2 DIF-analys

5.1.3 Kön

itemnr item
sdq1 Jag försöker vara vänlig mot andra. Jag bryr mig om deras känslor
sdq4 Jag delar ofta med mig till andra (t ex godis, spel, pennor)
sdq9 Jag är hjälpsam om någon är ledsen, upprörd eller känner sig dålig
sdq17 Jag är snäll mot yngre barn
sdq20 Jag ställer ofta upp och hjälper andra (föräldrar, lärare, andra barn)
Code
RIdifTable(df.pro, dif.gender)

Item 2 3 Mean location StDev MaxDiff
sdq1 -0.870 -0.739 -0.804 0.093 0.131
sdq4 0.719 0.485 0.602 0.165 0.234
sdq9 -0.075 0.314 0.119 0.275 0.388
sdq17 -0.258 -0.511 -0.385 0.179 0.253
sdq20 0.483 0.451 0.467 0.023 0.032
Code
RIdifFigure(df.pro, dif.gender)

Code
RIdifFigThresh(df.pro, dif.gender)

Inga items över gränsvärdet.

5.1.4 Årskurs

itemnr item
sdq1 Jag försöker vara vänlig mot andra. Jag bryr mig om deras känslor
sdq4 Jag delar ofta med mig till andra (t ex godis, spel, pennor)
sdq9 Jag är hjälpsam om någon är ledsen, upprörd eller känner sig dålig
sdq17 Jag är snäll mot yngre barn
sdq20 Jag ställer ofta upp och hjälper andra (föräldrar, lärare, andra barn)
Code
RIdifTable(df.pro, dif.arskurs)

Item 2 4 5 Mean location StDev MaxDiff
sdq1 -0.830 -0.788 -0.733 -0.783 0.049 0.097
sdq4 0.726 0.566 0.459 0.584 0.135 0.268
sdq9 0.090 0.117 0.238 0.148 0.079 0.149
sdq17 -0.473 -0.335 -0.459 -0.422 0.076 0.138
sdq20 0.487 0.439 0.494 0.473 0.030 0.055
Code
RIdifFigure(df.pro, dif.arskurs)

Code
RIdifFigThresh(df.pro, dif.arskurs)

Inga items över gränsvärdet.

5.1.5 Interaktion mellan kön och årskurs

Code
dfin <- df.pro

df.tree <- data.frame(matrix(ncol = 0, nrow = nrow(dfin)))
df.tree$difdata <- as.matrix(dfin)
df.tree$dif.gender <- dif.gender
df.tree$dif.arskurs <- dif.arskurs

pctree.out <- pctree(difdata ~ dif.gender + dif.arskurs, data = df.tree)
plot(pctree.out)

Code
cutoff <- 0.5
itempar(pctree.out) %>%
  as.data.frame() %>%
  t() %>%
  as.data.frame() %>%
  mutate(
    `Mean location` = rowMeans(.),
    StDev = rowSds(as.matrix(.))
  ) %>%
  rowwise() %>%
  mutate(MaxDiff = (max(c_across(c(1:(ncol(.) - 2))))) -
    min(c_across(c(1:(ncol(.) - 2))))) %>%
  ungroup() %>%
  mutate(across(where(is.numeric), round, 3)) %>%
  rownames_to_column(var = "Item") %>%
  mutate(Item = names(dfin)) %>%
  relocate(MaxDiff, .after = last_col()) %>%
  formattable(
    list(MaxDiff = formatter("span",
      style = ~ style(color = ifelse(MaxDiff < -cutoff,
        "red", ifelse(MaxDiff > cutoff, "red", "black")
      ))
    )),
    table.attr = "class=\"table table-striped\" style=\"font-size: 15px; font-family: Lato\""
  )
Item 4 5 6 8 9 Mean location StDev MaxDiff
sdq1 -0.861 -0.935 -0.777 -0.797 -0.709 -0.816 0.086 0.225
sdq4 0.783 0.775 0.558 0.651 0.396 0.633 0.162 0.387
sdq9 -0.185 -0.075 0.084 0.313 0.316 0.091 0.226 0.501
sdq17 -0.250 -0.193 -0.390 -0.625 -0.451 -0.382 0.171 0.432
sdq20 0.513 0.428 0.525 0.458 0.449 0.475 0.042 0.098

5.2 Emo

Code
df.delskala <- df.omit.na %>% 
  select(all_of(sdq.emo))
itemnr item
sdq3 Jag har ofta huvudvärk, ont i magen eller illamående
sdq8 Jag oroar mig mycket
sdq13 Jag är ofta ledsen, nedstämd eller gråtfärdig
sdq16 Jag blir nervös i nya situationer. Jag blir lätt osäker
sdq24 Jag är rädd för mycket, jag är lättskrämd
Code
RIitemfitPCM2(df.delskala, 300, 32, 8)
OutfitMSQ InfitMSQ OutfitZSTD InfitZSTD
sdq3 0.984 0.971 -0.253 -0.21
sdq8 0.728 0.733 -3.433 -3.684
sdq13 0.684 0.739 -2.853 -3.324
sdq16 0.926 0.927 -1.032 -1.071
sdq24 0.95 0.977 -0.371 -0.343
Code
RIpcmPCA(df.delskala)
PCA of Rasch model residuals
Eigenvalues
1.47
1.27
1.16
1.08
0.02
Code
RIresidcorr(df.delskala, cutoff = 0.2)
sdq3 sdq8 sdq13 sdq16 sdq24
sdq3
sdq8 -0.2
sdq13 -0.09 -0.04
sdq16 -0.3 -0.18 -0.24
sdq24 -0.29 -0.21 -0.23 -0.11
Note:
Relative cut-off value (highlighted in red) is 0.01, which is 0.2 above the average correlation.
Code
RIloadLoc(df.delskala)

Code
plot(mirt.rasch, type="trace")

Code
# increase fig-height above as needed, if you have many items
RItargeting(df.delskala)

Code
RIitemHierarchy(df.delskala)

Code
RItif(df.delskala)

Något låg item fit för några items, i övrigt ser unidimensionaliteten bra ut. Svarskategorierna fungerar bra. Targeting visar en golveffekt och reliabiliteten är låg.

5.2.1 DIF - interaktion mellan kön och årskurs

Code
dfin <- df.delskala

df.tree <- data.frame(matrix(ncol = 0, nrow = nrow(dfin)))
df.tree$difdata <- as.matrix(dfin)
df.tree$dif.gender <- dif.gender
df.tree$dif.arskurs <- dif.arskurs

pctree.out <- pctree(difdata ~ dif.gender + dif.arskurs, data = df.tree)
plot(pctree.out)

Code
cutoff <- 0.5
itempar(pctree.out) %>%
  as.data.frame() %>%
  t() %>%
  as.data.frame() %>%
  mutate(
    `Mean location` = rowMeans(.),
    StDev = rowSds(as.matrix(.))
  ) %>%
  rowwise() %>%
  mutate(MaxDiff = (max(c_across(c(1:(ncol(.) - 2))))) -
    min(c_across(c(1:(ncol(.) - 2))))) %>%
  ungroup() %>%
  mutate(across(where(is.numeric), round, 3)) %>%
  rownames_to_column(var = "Item") %>%
  mutate(Item = names(dfin)) %>%
  relocate(MaxDiff, .after = last_col()) %>%
  formattable(
    list(MaxDiff = formatter("span",
      style = ~ style(color = ifelse(MaxDiff < -cutoff,
        "red", ifelse(MaxDiff > cutoff, "red", "black")
      ))
    )),
    table.attr = "class=\"table table-striped\" style=\"font-size: 15px; font-family: Lato\""
  )
Item 3 4 7 8 10 11 Mean location StDev MaxDiff
sdq3 0.114 0.038 0.148 0.055 0.087 0.094 0.089 0.040 0.110
sdq8 -0.321 -0.239 -0.679 -0.837 -0.510 -0.746 -0.555 0.240 0.598
sdq13 0.494 0.600 0.571 0.476 0.591 0.685 0.570 0.076 0.209
sdq16 -0.661 -0.785 -0.673 -0.557 -0.911 -0.968 -0.759 0.158 0.411
sdq24 0.373 0.387 0.633 0.863 0.742 0.935 0.656 0.237 0.561

5.3 CPS

Code
df.delskala <- df.omit.na %>% 
  select(all_of(sdq.cps))
itemnr item
sdq5 Jag blir mycket arg och tappar ofta humöret
sdq7 Jag gör oftast som jag blir tillsagd
sdq12 Jag slåss eller bråkar mycket. Jag kan tvinga andra att göra som jag vill
sdq18 Jag blir ofta anklagad för att ljuga eller fuska
sdq22 Jag tar saker som inte tillhör mig, t ex från skolan eller andra ställen
Code
RIitemfitPCM2(df.delskala, 300, 32, 8)
OutfitMSQ InfitMSQ OutfitZSTD InfitZSTD
sdq5 0.842 0.844 -2.013 -2.245
sdq7 0.951 0.944 -0.606 -0.789
sdq12 0.447 0.62 -2.674 -2.564
sdq18 0.683 0.759 -2.111 -2.4
sdq22 0.696 0.783 -1.556 -1.395
Code
RIpcmPCA(df.delskala)
PCA of Rasch model residuals
Eigenvalues
1.50
1.25
1.15
1.06
0.03
Code
RIresidcorr(df.delskala, cutoff = 0.2)
sdq5 sdq7 sdq12 sdq18 sdq22
sdq5
sdq7 -0.26
sdq12 -0.02 -0.11
sdq18 -0.16 -0.16 -0.04
sdq22 -0.19 -0.14 0.03 -0.08
Note:
Relative cut-off value (highlighted in red) is 0.087, which is 0.2 above the average correlation.
Code
RIloadLoc(df.delskala)

Code
plot(mirt.rasch, type="trace")

Code
# increase fig-height above as needed, if you have many items
RItargeting(df.delskala)

Code
RIitemHierarchy(df.delskala)

Code
RItif(df.delskala)

Item 12 har mycket låg item fit. Det är också en illa formulerad fråga, eftersom den innehåller två frågor. Svarskategorierna är oordnade för 12 och 22, och 18 har mycket små avstånd mellan svarströsklarna. Item 12 bör tas bort, och 18 och 22 dikotomiseras eftersom svarskategorierna är oordnade. Även med dessa items inkluderade är reliabiliteten låg.

5.3.1 DIF - interaktion mellan kön och årskurs

Code
dfin <- df.delskala

df.tree <- data.frame(matrix(ncol = 0, nrow = nrow(dfin)))
df.tree$difdata <- as.matrix(dfin)
df.tree$dif.gender <- dif.gender
df.tree$dif.arskurs <- dif.arskurs

pctree.out <- pctree(difdata ~ dif.gender + dif.arskurs, data = df.tree)
plot(pctree.out)

Code
cutoff <- 0.5
itempar(pctree.out) %>%
  as.data.frame() %>%
  t() %>%
  as.data.frame() %>%
  mutate(
    `Mean location` = rowMeans(.),
    StDev = rowSds(as.matrix(.))
  ) %>%
  rowwise() %>%
  mutate(MaxDiff = (max(c_across(c(1:(ncol(.) - 2))))) -
    min(c_across(c(1:(ncol(.) - 2))))) %>%
  ungroup() %>%
  mutate(across(where(is.numeric), round, 3)) %>%
  rownames_to_column(var = "Item") %>%
  mutate(Item = names(dfin)) %>%
  relocate(MaxDiff, .after = last_col()) %>%
  formattable(
    list(MaxDiff = formatter("span",
      style = ~ style(color = ifelse(MaxDiff < -cutoff,
        "red", ifelse(MaxDiff > cutoff, "red", "black")
      ))
    )),
    table.attr = "class=\"table table-striped\" style=\"font-size: 15px; font-family: Lato\""
  )
Item 3 5 6 9 10 11 Mean location StDev MaxDiff
sdq5 -1.050 -1.072 -1.226 -0.369 -0.428 -0.414 -0.760 0.395 0.857
sdq7 -0.738 -0.650 -0.601 -0.624 -0.617 -0.819 -0.675 0.086 0.218
sdq12 1.140 0.859 0.925 0.806 0.771 0.658 0.860 0.164 0.482
sdq18 0.067 0.381 0.504 -0.224 -0.221 0.132 0.107 0.301 0.728
sdq22 0.581 0.482 0.398 0.411 0.495 0.443 0.468 0.067 0.183

5.4 Hyperaktivitet

Code
df.delskala <- df.omit.na %>% 
  select(all_of(sdq.hyp))
itemnr item
sdq2 Jag är rastlös. Jag kan inte vara stilla länge
sdq10 Jag har svårt att sitta stilla, jag vill jämt röra och vrida på mig
sdq15 Jag har svårt att koncentrera mig, jag är lättstörd
sdq21 Jag tänker mig för innan jag gör olika saker
sdq25 Jag kan koncentrera mig, göra klart det jag arbetar med
Code
RIitemfitPCM2(df.delskala, 300, 32, 8)
OutfitMSQ InfitMSQ OutfitZSTD InfitZSTD
sdq2 0.727 0.721 -3.819 -4.251
sdq10 0.721 0.724 -3.676 -3.879
sdq15 0.792 0.787 -2.633 -2.808
sdq21 1.215 1.194 2.52 2.368
sdq25 0.853 0.86 -2.028 -1.913
Code
RIpcmPCA(df.delskala)
PCA of Rasch model residuals
Eigenvalues
1.83
1.36
0.95
0.85
0.01
Code
RIresidcorr(df.delskala, cutoff = 0.2)
sdq2 sdq10 sdq15 sdq21 sdq25
sdq2
sdq10 0.23
sdq15 -0.24 -0.24
sdq21 -0.28 -0.31 -0.32
sdq25 -0.32 -0.35 0.05 -0.12
Note:
Relative cut-off value (highlighted in red) is 0.01, which is 0.2 above the average correlation.
Code
RIloadLoc(df.delskala)

Code
plot(mirt.rasch, type="trace")

Code
# increase fig-height above as needed, if you have many items
RItargeting(df.delskala)

Code
RIitemHierarchy(df.delskala)

Code
RItif(df.delskala)

Här finns problematiska residualkorrelationer mellan 2 och 10, samt (något mindre) mellan 15 och 25. Samtliga items har låg item fit ZSTD, utom 21 som ligger något högt. Item 21 sticker även ut något i 1st contrast loadings. Reliabiliteten låg.

Även här krävs åtgärder.

5.4.1 DIF - interaktion mellan kön och årskurs

Code
dfin <- df.delskala

df.tree <- data.frame(matrix(ncol = 0, nrow = nrow(dfin)))
df.tree$difdata <- as.matrix(dfin)
df.tree$dif.gender <- dif.gender
df.tree$dif.arskurs <- dif.arskurs

pctree.out <- pctree(difdata ~ dif.gender + dif.arskurs, data = df.tree)
plot(pctree.out)

Code
cutoff <- 0.5
itempar(pctree.out) %>%
  as.data.frame() %>%
  t() %>%
  as.data.frame() %>%
  mutate(
    `Mean location` = rowMeans(.),
    StDev = rowSds(as.matrix(.))
  ) %>%
  rowwise() %>%
  mutate(MaxDiff = (max(c_across(c(1:(ncol(.) - 2))))) -
    min(c_across(c(1:(ncol(.) - 2))))) %>%
  ungroup() %>%
  mutate(across(where(is.numeric), round, 3)) %>%
  rownames_to_column(var = "Item") %>%
  mutate(Item = names(dfin)) %>%
  relocate(MaxDiff, .after = last_col()) %>%
  formattable(
    list(MaxDiff = formatter("span",
      style = ~ style(color = ifelse(MaxDiff < -cutoff,
        "red", ifelse(MaxDiff > cutoff, "red", "black")
      ))
    )),
    table.attr = "class=\"table table-striped\" style=\"font-size: 15px; font-family: Lato\""
  )
Item 3 5 6 9 10 11 Mean location StDev MaxDiff
sdq2 -0.153 -0.259 -0.339 -0.228 -0.231 -0.342 -0.259 0.072 0.189
sdq10 -0.183 -0.002 -0.020 -0.315 -0.167 -0.215 -0.150 0.120 0.314
sdq15 -0.385 -0.488 -0.635 -0.073 -0.201 -0.316 -0.350 0.201 0.562
sdq21 0.457 0.695 0.996 0.106 0.236 0.675 0.528 0.328 0.890
sdq25 0.265 0.053 -0.002 0.510 0.364 0.198 0.231 0.192 0.512

5.5 Pps

Code
df.delskala <- df.omit.na %>% 
  select(all_of(sdq.pps))
itemnr item
sdq6 Jag är ofta för mig själv. Jag gör oftast saker ensam
sdq11 Jag har en eller flera kompisar
sdq14 Jämnåriga verkar gilla mig för det mesta
sdq19 Andra barn eller ungdomar retar eller mobbar mig
sdq23 Jag kommer bättre överens med vuxna än med jämnåriga
Code
RIitemfitPCM2(df.delskala, 300, 32, 8)
OutfitMSQ InfitMSQ OutfitZSTD InfitZSTD
sdq6 0.801 0.802 -2.231 -2.566
sdq11 0.439 0.634 -2.535 -2.463
sdq14 0.892 0.88 -1.326 -1.569
sdq19 0.712 0.795 -1.496 -1.45
sdq23 0.937 0.927 -0.931 -1.146
Code
RIpcmPCA(df.delskala)
PCA of Rasch model residuals
Eigenvalues
1.50
1.34
1.11
1.01
0.03
Code
RIresidcorr(df.delskala, cutoff = 0.2)
sdq6 sdq11 sdq14 sdq19 sdq23
sdq6
sdq11 -0.05
sdq14 -0.21 0.08
sdq19 -0.15 0 -0.07
sdq23 -0.18 -0.18 -0.28 -0.14
Note:
Relative cut-off value (highlighted in red) is 0.082, which is 0.2 above the average correlation.
Code
RIloadLoc(df.delskala)

Code
plot(mirt.rasch, type="trace")

Code
# increase fig-height above as needed, if you have many items
RItargeting(df.delskala)

Code
RIitemHierarchy(df.delskala)

Code
RItif(df.delskala)

Item 11 har mycket låg item fit, samt oordnade svarskategorier, och bör tas bort. Även item 19 har mycket små avstånd mellan svarströsklarna och bör dikotomiseras. Reliabiliteten är låg.

5.5.1 DIF - interaktion mellan kön och årskurs

Code
dfin <- df.delskala

df.tree <- data.frame(matrix(ncol = 0, nrow = nrow(dfin)))
df.tree$difdata <- as.matrix(dfin)
df.tree$dif.gender <- dif.gender
df.tree$dif.arskurs <- dif.arskurs

pctree.out <- pctree(difdata ~ dif.gender + dif.arskurs, data = df.tree)
plot(pctree.out)

Code
cutoff <- 0.5
itempar(pctree.out) %>%
  as.data.frame() %>%
  t() %>%
  as.data.frame() %>%
  mutate(
    `Mean location` = rowMeans(.),
    StDev = rowSds(as.matrix(.))
  ) %>%
  rowwise() %>%
  mutate(MaxDiff = (max(c_across(c(1:(ncol(.) - 2))))) -
    min(c_across(c(1:(ncol(.) - 2))))) %>%
  ungroup() %>%
  mutate(across(where(is.numeric), round, 3)) %>%
  rownames_to_column(var = "Item") %>%
  mutate(Item = names(dfin)) %>%
  relocate(MaxDiff, .after = last_col()) %>%
  formattable(
    list(MaxDiff = formatter("span",
      style = ~ style(color = ifelse(MaxDiff < -cutoff,
        "red", ifelse(MaxDiff > cutoff, "red", "black")
      ))
    )),
    table.attr = "class=\"table table-striped\" style=\"font-size: 15px; font-family: Lato\""
  )
Item 4 5 7 8 9 Mean location StDev MaxDiff
sdq6 -0.535 -0.391 -0.661 -0.577 -0.860 -0.605 0.173 0.469
sdq11 0.924 0.930 0.929 0.936 1.092 0.962 0.073 0.168
sdq14 -0.339 -0.315 -0.303 -0.200 -0.075 -0.246 0.109 0.264
sdq19 0.469 0.532 0.975 0.690 1.012 0.736 0.249 0.543
sdq23 -0.520 -0.757 -0.941 -0.849 -1.169 -0.847 0.239 0.649

6 Nästa steg

Att ta fram en fungerande uppsättning items som representerar Total Problem Score.

Utifrån den tidigare analysen påvisades flera stora residualkorrelationer. De item-par som uppvisade störst problem var:

  • 2 och 10 (rastlös / svårt att sitta stilla)
  • 8 och 13 (oro / ledsen, nedstämd, gråntfärdig)
  • 15 och 25 (koncentration)

I varje item-par bör ett item tas bort. Utifrån analyser av olika item-egenskaper ges följande motiveringar:

  • 2 har bättre spridning på svarströsklarna
  • 13 har lägre ZSTD, 8 bättre targeting
  • 15 har lägre ZSTD,

Vi tar bort 10, 13 och 25.

Code
tps.removed.items <- c("sdq10","sdq13","sdq25")

df.tps <- df.tps %>% 
  select(!any_of(tps.removed.items))

Fem items uppvisade problem med svarskategorierna. sdq11, sdq12, sdq18, sdq19, sdq22

Code
tps.erm <- PCM(df.tps)
plotICC(tps.erm, item.subset = tps.items.recode, ask = F)

Code
df.tps %>% 
  select(any_of(tps.items.recode)) %>% 
  RIbarplot()

6.0.1 Omkodning av svarskategorier

Vi slår samman svarskategori 1 och 2 för samtliga fem items.

Code
tps.items.recode <- c("sdq11","sdq12","sdq18","sdq19","sdq22")

df.tps <- df.tps %>% 
  mutate(across(any_of(tps.items.recode), ~ car::recode(.x,"2=1")))

7 TPS Rasch-analys 2

itemnr item
sdq2 Jag är rastlös. Jag kan inte vara stilla länge
sdq3 Jag har ofta huvudvärk, ont i magen eller illamående
sdq5 Jag blir mycket arg och tappar ofta humöret
sdq6 Jag är ofta för mig själv. Jag gör oftast saker ensam
sdq7 Jag gör oftast som jag blir tillsagd
sdq8 Jag oroar mig mycket
sdq11 Jag har en eller flera kompisar
sdq12 Jag slåss eller bråkar mycket. Jag kan tvinga andra att göra som jag vill
sdq14 Jämnåriga verkar gilla mig för det mesta
sdq15 Jag har svårt att koncentrera mig, jag är lättstörd
sdq16 Jag blir nervös i nya situationer. Jag blir lätt osäker
sdq18 Jag blir ofta anklagad för att ljuga eller fuska
sdq19 Andra barn eller ungdomar retar eller mobbar mig
sdq21 Jag tänker mig för innan jag gör olika saker
sdq22 Jag tar saker som inte tillhör mig, t ex från skolan eller andra ställen
sdq23 Jag kommer bättre överens med vuxna än med jämnåriga
sdq24 Jag är rädd för mycket, jag är lättskrämd
Code
RIitemfitPCM2(df.tps, 300, 32, 8)
OutfitMSQ InfitMSQ OutfitZSTD InfitZSTD
sdq2 0.959 0.963 -0.435 -0.783
sdq3 0.884 0.905 -1.321 -1.494
sdq5 0.792 0.824 -2.452 -2.456
sdq6 1.039 1.017 0.536 0.447
sdq7 1.151 1.125 2.002 1.691
sdq8 0.908 0.916 -1.305 -1.131
sdq11 0.749 0.911 -1.289 -0.581
sdq12 0.77 0.902 -1.124 -0.701
sdq14 0.973 0.977 -0.278 -0.28
sdq15 0.833 0.847 -2.566 -2.662
sdq16 0.962 0.959 -0.431 -0.594
sdq18 0.914 0.951 -0.831 -0.467
sdq19 0.761 0.891 -1.345 -1.005
sdq21 1.076 1.069 0.93 0.844
sdq22 0.931 0.955 -0.387 -0.4
sdq23 1.175 1.122 2.069 1.672
sdq24 0.964 0.967 -0.464 -0.305
Code
RIpcmPCA(df.tps)
PCA of Rasch model residuals
Eigenvalues
2.27
1.85
1.22
1.17
1.08
Code
RIresidcorr(df.tps, cutoff = 0.20)
sdq2 sdq3 sdq5 sdq6 sdq7 sdq8 sdq11 sdq12 sdq14 sdq15 sdq16 sdq18 sdq19 sdq21 sdq22 sdq23 sdq24
sdq2
sdq3 -0.07
sdq5 0.09 0.02
sdq6 -0.21 -0.1 -0.13
sdq7 0.04 -0.16 -0.02 -0.18
sdq8 -0.15 0.16 -0.04 -0.01 -0.26
sdq11 -0.14 -0.08 -0.1 0.16 -0.03 -0.06
sdq12 0.05 -0.09 0.14 -0.08 0.08 -0.16 0.03
sdq14 -0.18 -0.11 -0.13 0.07 0 -0.12 0.23 -0.06
sdq15 0.22 -0.02 0.06 -0.17 -0.05 -0.06 -0.14 -0.01 -0.16
sdq16 -0.16 0.03 -0.11 0.01 -0.26 0.22 -0.07 -0.18 -0.05 0
sdq18 0.04 -0.11 0.05 -0.09 0.08 -0.2 0.01 0.17 -0.03 -0.01 -0.19
sdq19 -0.11 -0.03 -0.06 0.03 -0.07 -0.04 0.17 0.08 0.08 -0.06 -0.07 0.13
sdq21 0.08 -0.15 0.03 -0.2 0.19 -0.27 -0.02 0.09 0 -0.01 -0.22 0.08 -0.07
sdq22 0 -0.1 0 -0.05 0.06 -0.15 0.02 0.2 -0.05 -0.05 -0.13 0.15 0.07 0.05
sdq23 -0.17 -0.09 -0.15 0.13 -0.14 -0.07 0.04 -0.06 0.01 -0.14 -0.11 -0.07 0.02 -0.2 -0.05
sdq24 -0.14 0.01 -0.09 -0.07 -0.19 0.15 -0.05 -0.12 -0.09 -0.09 0.17 -0.13 -0.01 -0.17 -0.08 -0.08
Note:
Relative cut-off value (highlighted in red) is 0.161, which is 0.2 above the average correlation.
Code
RIloadLoc(df.tps)

Code
# increase fig-height above as needed, if you have many items
RItargeting(df.tps)

Code
RIitemHierarchy(df.tps)

Item fit ser bra ut. PCA av residualer överstiger dock fortfarande 2.0. Tre item-par har korrelationer som överstiger genomsnittskorrelationen mer än 0.25.

  • 2 och 15 (rastlös / svårt att koncentrera mig)
  • 11 och 14 (har kompisar / jämnåriga verkar gilla mig)
  • 8 och 16 (oro / nervös, osäker)

Resonemang kring itemreduktion:

  • 15 har sämre ZSTD än 2, men vi testar att kombinera dem eftersom deras svarströsklar har olika spridning
  • 11 har sämre targeting och hade problem med svarskategorierna
  • 16 (nervös och osäker) har två frågor i en, och ter sig mindre relevant än 8 (oro)
Code
tps.removed.items <- c("sdq10","sdq13","sdq25","sdq11","sdq16")

df.tps2 <- df.tps %>% 
  select(!any_of(tps.removed.items)) %>% 
  mutate(sdq2_15 = sdq2 + sdq15) %>% 
  select(!sdq2) %>% 
  select(!sdq15)

7.1 Sammanslaget item

Code
tps.erm <- PCM(df.tps2)
plotICC(tps.erm, item.subset = "sdq2_15", ask = F)

Code
RItileplot(df.tps2)

8 TPS Rasch-analys 3

itemnr item
sdq3 Jag har ofta huvudvärk, ont i magen eller illamående
sdq5 Jag blir mycket arg och tappar ofta humöret
sdq6 Jag är ofta för mig själv. Jag gör oftast saker ensam
sdq7 Jag gör oftast som jag blir tillsagd
sdq8 Jag oroar mig mycket
sdq12 Jag slåss eller bråkar mycket. Jag kan tvinga andra att göra som jag vill
sdq14 Jämnåriga verkar gilla mig för det mesta
sdq18 Jag blir ofta anklagad för att ljuga eller fuska
sdq19 Andra barn eller ungdomar retar eller mobbar mig
sdq21 Jag tänker mig för innan jag gör olika saker
sdq22 Jag tar saker som inte tillhör mig, t ex från skolan eller andra ställen
sdq23 Jag kommer bättre överens med vuxna än med jämnåriga
sdq24 Jag är rädd för mycket, jag är lättskrämd
Code
RIitemfitPCM2(df.tps2, 300, 32, 8)
OutfitMSQ InfitMSQ OutfitZSTD InfitZSTD
sdq3 0.87 0.895 -1.695 -1.573
sdq5 0.756 0.792 -2.843 -3.024
sdq6 1.042 1.02 0.627 0.363
sdq7 1.087 1.07 1.202 1.149
sdq8 0.939 0.942 -0.712 -1.189
sdq12 0.717 0.883 -1.458 -0.824
sdq14 0.967 0.976 -0.438 -0.137
sdq18 0.869 0.927 -1.111 -0.977
sdq19 0.749 0.89 -1.501 -0.968
sdq21 1.028 1.024 0.37 0.403
sdq22 0.887 0.938 -0.475 -0.513
sdq23 1.133 1.095 1.555 1.29
sdq24 0.982 0.981 -0.22 -0.297
sdq2_15 0.873 0.872 -1.74 -1.893
Code
RIpcmPCA(df.tps2)
PCA of Rasch model residuals
Eigenvalues
2.03
1.60
1.23
1.13
1.04
Code
RIresidcorr(df.tps2, cutoff = 0.20)
sdq3 sdq5 sdq6 sdq7 sdq8 sdq12 sdq14 sdq18 sdq19 sdq21 sdq22 sdq23 sdq24 sdq2_15
sdq3
sdq5 0.03
sdq6 -0.08 -0.12
sdq7 -0.18 -0.03 -0.18
sdq8 0.19 -0.02 0.02 -0.26
sdq12 -0.09 0.14 -0.08 0.07 -0.15
sdq14 -0.1 -0.12 0.09 0 -0.1 -0.06
sdq18 -0.11 0.04 -0.09 0.06 -0.2 0.17 -0.03
sdq19 -0.02 -0.05 0.04 -0.08 -0.03 0.08 0.09 0.13
sdq21 -0.16 0.02 -0.2 0.17 -0.26 0.08 0 0.07 -0.08
sdq22 -0.1 0 -0.05 0.05 -0.14 0.2 -0.05 0.15 0.07 0.04
sdq23 -0.09 -0.16 0.13 -0.16 -0.05 -0.07 0.02 -0.08 0.02 -0.22 -0.05
sdq24 0.03 -0.07 -0.05 -0.2 0.18 -0.12 -0.07 -0.12 0 -0.17 -0.07 -0.07
sdq2_15 -0.07 0.06 -0.25 -0.03 -0.13 0 -0.22 -0.01 -0.12 0.03 -0.05 -0.22 -0.15
Note:
Relative cut-off value (highlighted in red) is 0.158, which is 0.2 above the average correlation.
Code
# increase fig-height above as needed, if you have many items
RItargeting(df.tps2)

Code
RIitemHierarchy(df.tps2)

Klart bättre, men fortfarande något hög PCA och några residualkorrelationer kvarstår. Item 12 hade problem med svarskategorierna och har residualkorrelationer med två andra items. Vi tar bort item 12 och gör om analysen.

Code
tps.removed.items <- c("sdq10","sdq13","sdq25","sdq11","sdq16","sdq12")

df.tps2 <- df.tps2 %>% 
  select(!any_of(tps.removed.items))

9 TPS Rasch-analys 4

itemnr item
sdq3 Jag har ofta huvudvärk, ont i magen eller illamående
sdq5 Jag blir mycket arg och tappar ofta humöret
sdq6 Jag är ofta för mig själv. Jag gör oftast saker ensam
sdq7 Jag gör oftast som jag blir tillsagd
sdq8 Jag oroar mig mycket
sdq14 Jämnåriga verkar gilla mig för det mesta
sdq18 Jag blir ofta anklagad för att ljuga eller fuska
sdq19 Andra barn eller ungdomar retar eller mobbar mig
sdq21 Jag tänker mig för innan jag gör olika saker
sdq22 Jag tar saker som inte tillhör mig, t ex från skolan eller andra ställen
sdq23 Jag kommer bättre överens med vuxna än med jämnåriga
sdq24 Jag är rädd för mycket, jag är lättskrämd
Code
RIitemfitPCM2(df.tps2, 300, 32, 8)
OutfitMSQ InfitMSQ OutfitZSTD InfitZSTD
sdq3 0.857 0.881 -1.54 -1.833
sdq5 0.759 0.795 -2.988 -2.827
sdq6 1.028 1.007 0.413 0.275
sdq7 1.087 1.069 0.872 0.769
sdq8 0.921 0.925 -1.003 -1.372
sdq14 0.958 0.966 -0.5 -0.379
sdq18 0.874 0.932 -1.205 -0.898
sdq19 0.748 0.89 -1.448 -0.989
sdq21 1.028 1.024 0.207 0.514
sdq22 0.895 0.945 -0.622 -0.458
sdq23 1.121 1.084 1.76 1.185
sdq24 0.963 0.963 -0.309 -0.524
sdq2_15 0.863 0.863 -1.699 -1.952
Code
RIpcmPCA(df.tps2)
PCA of Rasch model residuals
Eigenvalues
1.96
1.60
1.16
1.13
1.03
Code
RIresidcorr(df.tps2, cutoff = 0.20)
sdq3 sdq5 sdq6 sdq7 sdq8 sdq14 sdq18 sdq19 sdq21 sdq22 sdq23 sdq24 sdq2_15
sdq3
sdq5 0.03
sdq6 -0.08 -0.12
sdq7 -0.17 -0.03 -0.18
sdq8 0.18 -0.02 0.01 -0.26
sdq14 -0.1 -0.11 0.08 0 -0.1
sdq18 -0.11 0.05 -0.08 0.07 -0.19 -0.02
sdq19 -0.02 -0.04 0.05 -0.07 -0.03 0.09 0.14
sdq21 -0.16 0.03 -0.2 0.17 -0.26 0 0.07 -0.07
sdq22 -0.09 0.01 -0.05 0.05 -0.13 -0.05 0.15 0.08 0.04
sdq23 -0.09 -0.15 0.13 -0.16 -0.06 0.01 -0.07 0.03 -0.22 -0.05
sdq24 0.03 -0.07 -0.05 -0.2 0.18 -0.07 -0.12 0.01 -0.17 -0.07 -0.08
sdq2_15 -0.07 0.07 -0.25 -0.03 -0.13 -0.22 0 -0.12 0.03 -0.04 -0.22 -0.15
Note:
Relative cut-off value (highlighted in red) is 0.151, which is 0.2 above the average correlation.
Code
# increase fig-height above as needed, if you have many items
RItargeting(df.tps2)

Code
RIitemHierarchy(df.tps2)

Några item-par uppvisar fortfarande smärre problem. Men det är relativt nära gränsvärdet och PCA visar att största eigenvalue nu är under 2.0.

9.1 DIF-analys

9.1.1 Kön

itemnr item
sdq3 Jag har ofta huvudvärk, ont i magen eller illamående
sdq5 Jag blir mycket arg och tappar ofta humöret
sdq6 Jag är ofta för mig själv. Jag gör oftast saker ensam
sdq7 Jag gör oftast som jag blir tillsagd
sdq8 Jag oroar mig mycket
sdq14 Jämnåriga verkar gilla mig för det mesta
sdq18 Jag blir ofta anklagad för att ljuga eller fuska
sdq19 Andra barn eller ungdomar retar eller mobbar mig
sdq21 Jag tänker mig för innan jag gör olika saker
sdq22 Jag tar saker som inte tillhör mig, t ex från skolan eller andra ställen
sdq23 Jag kommer bättre överens med vuxna än med jämnåriga
sdq24 Jag är rädd för mycket, jag är lättskrämd
Code
RIdifTable(df.tps2, dif.gender)

Item 2 3 Mean location StDev MaxDiff
sdq3 -0.678 0.153 -0.263 0.588 0.831
sdq5 -0.261 -0.009 -0.135 0.178 0.252
sdq6 -0.088 -0.145 -0.117 0.040 0.057
sdq7 0.120 -0.219 -0.050 0.239 0.338
sdq8 -1.231 -0.287 -0.759 0.667 0.944
sdq14 0.260 0.231 0.246 0.020 0.029
sdq18 0.833 -0.152 0.341 0.697 0.985
sdq19 1.050 0.853 0.951 0.140 0.197
sdq21 0.015 -0.361 -0.173 0.266 0.376
sdq22 1.338 0.606 0.972 0.518 0.732
sdq23 -0.234 -0.413 -0.324 0.127 0.179
sdq24 -0.278 0.602 0.162 0.622 0.880
sdq2_15 -0.846 -0.858 -0.852 0.009 0.013
Code
RIdifFigure(df.tps2, dif.gender)

Code
RIdifFigThresh(df.tps2, dif.gender)

5 items uppvisar problem med DIF för kön över gränsvärdet 0.5.

9.1.2 Årskurs

itemnr item
sdq3 Jag har ofta huvudvärk, ont i magen eller illamående
sdq5 Jag blir mycket arg och tappar ofta humöret
sdq6 Jag är ofta för mig själv. Jag gör oftast saker ensam
sdq7 Jag gör oftast som jag blir tillsagd
sdq8 Jag oroar mig mycket
sdq14 Jämnåriga verkar gilla mig för det mesta
sdq18 Jag blir ofta anklagad för att ljuga eller fuska
sdq19 Andra barn eller ungdomar retar eller mobbar mig
sdq21 Jag tänker mig för innan jag gör olika saker
sdq22 Jag tar saker som inte tillhör mig, t ex från skolan eller andra ställen
sdq23 Jag kommer bättre överens med vuxna än med jämnåriga
sdq24 Jag är rädd för mycket, jag är lättskrämd
Code
RIdifTable(df.tps2, dif.arskurs)

Item 3 4 5 Mean location StDev MaxDiff
sdq3 -0.207 -0.245 -0.484 -0.312 0.150 0.277
sdq5 -0.153 -0.135 -0.100 -0.129 0.027 0.053
sdq6 0.031 -0.087 -0.301 -0.119 0.168 0.332
sdq7 -0.093 -0.005 0.011 -0.029 0.056 0.104
sdq8 -0.490 -0.780 -1.100 -0.790 0.305 0.610
sdq14 0.182 0.241 0.384 0.269 0.104 0.203
sdq18 0.064 0.318 0.689 0.357 0.314 0.624
sdq19 0.740 0.922 1.399 1.020 0.340 0.659
sdq21 -0.284 -0.149 -0.020 -0.151 0.132 0.264
sdq22 1.054 0.853 0.970 0.959 0.101 0.201
sdq23 -0.103 -0.314 -0.552 -0.323 0.225 0.449
sdq24 0.023 0.151 0.114 0.096 0.066 0.128
sdq2_15 -0.763 -0.772 -1.010 -0.848 0.140 0.246
Code
RIdifFigure(df.tps2, dif.arskurs)

Code
RIdifFigThresh(df.tps2, dif.arskurs)

Tre items går över gränsvärdet gällande årskurs.

9.1.3 Interaktion mellan kön och årskurs

Code
dfin <- df.tps2

df.tree <- data.frame(matrix(ncol = 0, nrow = nrow(dfin)))
df.tree$difdata <- as.matrix(dfin)
df.tree$dif.gender <- dif.gender
df.tree$dif.arskurs <- dif.arskurs

pctree.out <- pctree(difdata ~ dif.gender + dif.arskurs, data = df.tree)
plot(pctree.out)

Code
cutoff <- 0.5
itempar(pctree.out) %>%
  as.data.frame() %>%
  t() %>%
  as.data.frame() %>%
  mutate(
    `Mean location` = rowMeans(.),
    StDev = rowSds(as.matrix(.))
  ) %>%
  rowwise() %>%
  mutate(MaxDiff = (max(c_across(c(1:(ncol(.) - 2))))) -
    min(c_across(c(1:(ncol(.) - 2))))) %>%
  ungroup() %>%
  mutate(across(where(is.numeric), round, 3)) %>%
  rownames_to_column(var = "Item") %>%
  mutate(Item = names(dfin)) %>%
  relocate(MaxDiff, .after = last_col()) %>%
  formattable(
    list(MaxDiff = formatter("span",
      style = ~ style(color = ifelse(MaxDiff < -cutoff,
        "red", ifelse(MaxDiff > cutoff, "red", "black")
      ))
    )),
    table.attr = "class=\"table table-striped\" style=\"font-size: 15px; font-family: Lato\""
  )
Item 3 5 6 9 10 11 Mean location StDev MaxDiff
sdq3 -0.532 -0.640 -0.933 0.194 0.208 0.026 -0.279 0.485 1.142
sdq5 -0.279 -0.257 -0.271 -0.033 -0.041 0.050 -0.139 0.147 0.328
sdq6 0.005 -0.101 -0.230 0.035 -0.115 -0.416 -0.137 0.166 0.451
sdq7 0.010 0.123 0.283 -0.236 -0.179 -0.264 -0.044 0.220 0.547
sdq8 -0.893 -1.309 -1.659 -0.037 -0.259 -0.625 -0.797 0.618 1.622
sdq14 0.205 0.214 0.374 0.128 0.232 0.361 0.252 0.096 0.246
sdq18 0.473 0.928 1.299 -0.348 -0.220 0.195 0.388 0.645 1.647
sdq19 0.731 1.043 1.625 0.718 0.764 1.163 1.007 0.354 0.907
sdq21 -0.102 0.086 0.062 -0.498 -0.403 -0.139 -0.166 0.240 0.585
sdq22 1.425 1.262 1.299 0.699 0.470 0.654 0.968 0.406 0.955
sdq23 0.031 -0.327 -0.474 -0.274 -0.346 -0.677 -0.345 0.234 0.708
sdq24 -0.319 -0.251 -0.288 0.461 0.708 0.661 0.162 0.498 1.027
sdq2_15 -0.756 -0.772 -1.086 -0.808 -0.821 -0.988 -0.872 0.134 0.330

Alla items utom 4 uppvisar stora problem.

9.2 DIF-analys 2

Det är tydligt att vi ser påtagliga problem med DIF när vi har data från både pojkar och flickor i årskurs 7, 9 och 2:an på gymnasiet. Vi provar att ta bort årskurs 7 ur samplet och gör om analyserna.

Code
# new dataframe for only åk 9 and gy 2
df.tps3 <- df.tps2
df.tps3$arskurs <- dif.arskurs
df.tps3$gender <- dif.gender

df.tps3 <- df.tps3 %>% 
  filter(!arskurs == "Åk 7")

dif2.arskurs <- df.tps3$arskurs
dif2.gender <- df.tps3$gender
df.tps3$arskurs <- NULL
df.tps3$gender <- NULL

# new dataframe for only åk 7
df.tps7 <- df.tps2
df.tps7$arskurs <- dif.arskurs
df.tps7$gender <- dif.gender

df.tps7 <- df.tps7 %>% 
  filter(arskurs == "Åk 7")

dif7.arskurs <- df.tps7$arskurs
dif7.gender <- df.tps7$gender
df.tps7$arskurs <- NULL
df.tps7$gender <- NULL

# new dataframe for only åk 9
df.tps9 <- df.tps2
df.tps9$arskurs <- dif.arskurs
df.tps9$gender <- dif.gender

df.tps9 <- df.tps9 %>% 
  filter(arskurs == "Åk 9")

dif9.arskurs <- df.tps9$arskurs
dif9.gender <- df.tps9$gender
df.tps9$arskurs <- NULL
df.tps9$gender <- NULL

# new dataframe for only gy 2
df.tpsGy2 <- df.tps2
df.tpsGy2$arskurs <- dif.arskurs
df.tpsGy2$gender <- dif.gender

df.tpsGy2 <- df.tpsGy2 %>% 
  filter(arskurs == "Gy 2")

difGy2.arskurs <- df.tpsGy2$arskurs
difGy2.gender <- df.tpsGy2$gender
df.tpsGy2$arskurs <- NULL
df.tpsGy2$gender <- NULL

9.2.1 Kön

itemnr item
sdq3 Jag har ofta huvudvärk, ont i magen eller illamående
sdq5 Jag blir mycket arg och tappar ofta humöret
sdq6 Jag är ofta för mig själv. Jag gör oftast saker ensam
sdq7 Jag gör oftast som jag blir tillsagd
sdq8 Jag oroar mig mycket
sdq14 Jämnåriga verkar gilla mig för det mesta
sdq18 Jag blir ofta anklagad för att ljuga eller fuska
sdq19 Andra barn eller ungdomar retar eller mobbar mig
sdq21 Jag tänker mig för innan jag gör olika saker
sdq22 Jag tar saker som inte tillhör mig, t ex från skolan eller andra ställen
sdq23 Jag kommer bättre överens med vuxna än med jämnåriga
sdq24 Jag är rädd för mycket, jag är lättskrämd
Code
RIdifTable(df.tps3, dif2.gender)

Item 2 3 Mean location StDev MaxDiff
sdq3 -0.766 0.129 -0.318 0.633 0.896
sdq5 -0.258 0.001 -0.128 0.183 0.259
sdq6 -0.152 -0.246 -0.199 0.067 0.094
sdq7 0.187 -0.213 -0.013 0.283 0.400
sdq8 -1.452 -0.421 -0.937 0.729 1.031
sdq14 0.286 0.288 0.287 0.002 0.003
sdq18 1.080 -0.040 0.520 0.792 1.120
sdq19 1.265 0.929 1.097 0.238 0.337
sdq21 0.081 -0.286 -0.103 0.260 0.368
sdq22 1.283 0.552 0.917 0.516 0.730
sdq23 -0.386 -0.491 -0.438 0.074 0.105
sdq24 -0.262 0.689 0.214 0.672 0.951
sdq2_15 -0.906 -0.891 -0.898 0.010 0.014
Code
RIdifFigure(df.tps3, dif2.gender)

Code
RIdifFigThresh(df.tps3, dif2.gender)

Samma 5 items uppvisar problem med DIF för kön över gränsvärdet 0.5.

Code
df.tps3 %>% 
  select(sdq3,sdq8,sdq18,sdq22,sdq24) %>% 
  RIlistitems()
itemnr item
sdq3 Jag har ofta huvudvärk, ont i magen eller illamående
sdq8 Jag oroar mig mycket
sdq18 Jag blir ofta anklagad för att ljuga eller fuska
sdq22 Jag tar saker som inte tillhör mig, t ex från skolan eller andra ställen
sdq24 Jag är rädd för mycket, jag är lättskrämd

9.2.2 Årskurs

itemnr item
sdq3 Jag har ofta huvudvärk, ont i magen eller illamående
sdq5 Jag blir mycket arg och tappar ofta humöret
sdq6 Jag är ofta för mig själv. Jag gör oftast saker ensam
sdq7 Jag gör oftast som jag blir tillsagd
sdq8 Jag oroar mig mycket
sdq14 Jämnåriga verkar gilla mig för det mesta
sdq18 Jag blir ofta anklagad för att ljuga eller fuska
sdq19 Andra barn eller ungdomar retar eller mobbar mig
sdq21 Jag tänker mig för innan jag gör olika saker
sdq22 Jag tar saker som inte tillhör mig, t ex från skolan eller andra ställen
sdq23 Jag kommer bättre överens med vuxna än med jämnåriga
sdq24 Jag är rädd för mycket, jag är lättskrämd
Code
RIdifTable(df.tps3, dif2.arskurs)

Item 2 3 Mean location StDev MaxDiff
sdq3 -0.245 -0.484 -0.365 0.169 0.240
sdq5 -0.135 -0.100 -0.117 0.025 0.035
sdq6 -0.087 -0.301 -0.194 0.151 0.214
sdq7 -0.005 0.011 0.003 0.011 0.016
sdq8 -0.780 -1.100 -0.940 0.227 0.321
sdq14 0.241 0.384 0.313 0.101 0.143
sdq18 0.318 0.689 0.503 0.262 0.371
sdq19 0.922 1.399 1.161 0.337 0.476
sdq21 -0.149 -0.020 -0.085 0.091 0.129
sdq22 0.853 0.970 0.912 0.082 0.116
sdq23 -0.314 -0.552 -0.433 0.168 0.237
sdq24 0.151 0.114 0.133 0.026 0.037
sdq2_15 -0.772 -1.010 -0.891 0.168 0.238
Code
RIdifFigure(df.tps3, dif2.arskurs)

Code
RIdifFigThresh(df.tps3, dif2.arskurs)

Ingen DIF mellan åk 9 och gy 2. Dock är item 19 nära (0.476) gränsvärdet på 0.5, och både 18 och 8 går över 0.3.

itemnr item
sdq3 Jag har ofta huvudvärk, ont i magen eller illamående
sdq5 Jag blir mycket arg och tappar ofta humöret
sdq6 Jag är ofta för mig själv. Jag gör oftast saker ensam
sdq7 Jag gör oftast som jag blir tillsagd
sdq8 Jag oroar mig mycket
sdq14 Jämnåriga verkar gilla mig för det mesta
sdq18 Jag blir ofta anklagad för att ljuga eller fuska
sdq19 Andra barn eller ungdomar retar eller mobbar mig
sdq21 Jag tänker mig för innan jag gör olika saker
sdq22 Jag tar saker som inte tillhör mig, t ex från skolan eller andra ställen
sdq23 Jag kommer bättre överens med vuxna än med jämnåriga
sdq24 Jag är rädd för mycket, jag är lättskrämd

9.2.3 Interaktion mellan kön och årskurs

Code
dfin <- df.tps3

df.tree <- data.frame(matrix(ncol = 0, nrow = nrow(dfin)))
df.tree$difdata <- as.matrix(dfin)
df.tree$dif.gender <- dif2.gender
df.tree$dif.arskurs <- dif2.arskurs

pctree.out <- pctree(difdata ~ dif.gender + dif.arskurs, data = df.tree)
plot(pctree.out)

Code
cutoff <- 0.5
itempar(pctree.out) %>%
  as.data.frame() %>%
  t() %>%
  as.data.frame() %>%
  mutate(
    `Mean location` = rowMeans(.),
    StDev = rowSds(as.matrix(.))
  ) %>%
  rowwise() %>%
  mutate(MaxDiff = (max(c_across(c(1:(ncol(.) - 2))))) -
    min(c_across(c(1:(ncol(.) - 2))))) %>%
  ungroup() %>%
  mutate(across(where(is.numeric), round, 3)) %>%
  rownames_to_column(var = "Item") %>%
  mutate(Item = names(dfin)) %>%
  relocate(MaxDiff, .after = last_col()) %>%
  formattable(
    list(MaxDiff = formatter("span",
      style = ~ style(color = ifelse(MaxDiff < -cutoff,
        "red", ifelse(MaxDiff > cutoff, "red", "black")
      ))
    )),
    table.attr = "class=\"table table-striped\" style=\"font-size: 15px; font-family: Lato\""
  )
Item 3 4 6 7 Mean location StDev MaxDiff
sdq3 -0.640 -0.933 0.208 0.026 -0.335 0.541 1.142
sdq5 -0.257 -0.271 -0.041 0.050 -0.130 0.160 0.321
sdq6 -0.101 -0.230 -0.115 -0.416 -0.215 0.146 0.315
sdq7 0.123 0.283 -0.179 -0.264 -0.009 0.256 0.547
sdq8 -1.309 -1.659 -0.259 -0.625 -0.963 0.636 1.401
sdq14 0.214 0.374 0.232 0.361 0.295 0.084 0.160
sdq18 0.928 1.299 -0.220 0.195 0.551 0.689 1.519
sdq19 1.043 1.625 0.764 1.163 1.149 0.359 0.861
sdq21 0.086 0.062 -0.403 -0.139 -0.099 0.227 0.489
sdq22 1.262 1.299 0.470 0.654 0.921 0.422 0.829
sdq23 -0.327 -0.474 -0.346 -0.677 -0.456 0.161 0.350
sdq24 -0.251 -0.288 0.708 0.661 0.207 0.551 0.996
sdq2_15 -0.772 -1.086 -0.821 -0.988 -0.917 0.146 0.314

7 items har stora problem med interaktion mellan årskurs och kön, d.v.s. 2 fler än de som bara hade DIF för kön.

9.3 DIF kön, åk 7

itemnr item
sdq3 Jag har ofta huvudvärk, ont i magen eller illamående
sdq5 Jag blir mycket arg och tappar ofta humöret
sdq6 Jag är ofta för mig själv. Jag gör oftast saker ensam
sdq7 Jag gör oftast som jag blir tillsagd
sdq8 Jag oroar mig mycket
sdq14 Jämnåriga verkar gilla mig för det mesta
sdq18 Jag blir ofta anklagad för att ljuga eller fuska
sdq19 Andra barn eller ungdomar retar eller mobbar mig
sdq21 Jag tänker mig för innan jag gör olika saker
sdq22 Jag tar saker som inte tillhör mig, t ex från skolan eller andra ställen
sdq23 Jag kommer bättre överens med vuxna än med jämnåriga
sdq24 Jag är rädd för mycket, jag är lättskrämd
Code
RIdifTable(df.tps7, dif7.gender)

Item 2 3 Mean location StDev MaxDiff
sdq3 -0.532 0.194 -0.169 0.514 0.726
sdq5 -0.279 -0.033 -0.156 0.174 0.246
sdq6 0.005 0.035 0.020 0.022 0.030
sdq7 0.010 -0.236 -0.113 0.174 0.246
sdq8 -0.893 -0.037 -0.465 0.605 0.856
sdq14 0.205 0.128 0.166 0.054 0.077
sdq18 0.473 -0.348 0.063 0.581 0.821
sdq19 0.731 0.718 0.725 0.009 0.013
sdq21 -0.102 -0.498 -0.300 0.280 0.396
sdq22 1.425 0.699 1.062 0.513 0.726
sdq23 0.031 -0.274 -0.122 0.216 0.305
sdq24 -0.319 0.461 0.071 0.551 0.779
sdq2_15 -0.756 -0.808 -0.782 0.037 0.052

Samma items har även problem när vi tittar separat på årskurs 7.

9.4 DIF kön, åk 9

itemnr item
sdq3 Jag har ofta huvudvärk, ont i magen eller illamående
sdq5 Jag blir mycket arg och tappar ofta humöret
sdq6 Jag är ofta för mig själv. Jag gör oftast saker ensam
sdq7 Jag gör oftast som jag blir tillsagd
sdq8 Jag oroar mig mycket
sdq14 Jämnåriga verkar gilla mig för det mesta
sdq18 Jag blir ofta anklagad för att ljuga eller fuska
sdq19 Andra barn eller ungdomar retar eller mobbar mig
sdq21 Jag tänker mig för innan jag gör olika saker
sdq22 Jag tar saker som inte tillhör mig, t ex från skolan eller andra ställen
sdq23 Jag kommer bättre överens med vuxna än med jämnåriga
sdq24 Jag är rädd för mycket, jag är lättskrämd
Code
RIdifTable(df.tps9, dif9.gender)

Item 2 3 Mean location StDev MaxDiff
sdq3 -0.640 0.208 -0.216 0.600 0.849
sdq5 -0.257 -0.041 -0.149 0.153 0.216
sdq6 -0.101 -0.115 -0.108 0.010 0.014
sdq7 0.123 -0.179 -0.028 0.214 0.302
sdq8 -1.309 -0.259 -0.784 0.743 1.050
sdq14 0.214 0.232 0.223 0.013 0.018
sdq18 0.928 -0.220 0.354 0.812 1.148
sdq19 1.043 0.764 0.903 0.197 0.279
sdq21 0.086 -0.403 -0.158 0.346 0.489
sdq22 1.262 0.470 0.866 0.560 0.793
sdq23 -0.327 -0.346 -0.336 0.013 0.019
sdq24 -0.251 0.708 0.228 0.678 0.959
sdq2_15 -0.772 -0.821 -0.796 0.034 0.049

9.5 DIF kön, gy 2

itemnr item
sdq3 Jag har ofta huvudvärk, ont i magen eller illamående
sdq5 Jag blir mycket arg och tappar ofta humöret
sdq6 Jag är ofta för mig själv. Jag gör oftast saker ensam
sdq7 Jag gör oftast som jag blir tillsagd
sdq8 Jag oroar mig mycket
sdq14 Jämnåriga verkar gilla mig för det mesta
sdq18 Jag blir ofta anklagad för att ljuga eller fuska
sdq19 Andra barn eller ungdomar retar eller mobbar mig
sdq21 Jag tänker mig för innan jag gör olika saker
sdq22 Jag tar saker som inte tillhör mig, t ex från skolan eller andra ställen
sdq23 Jag kommer bättre överens med vuxna än med jämnåriga
sdq24 Jag är rädd för mycket, jag är lättskrämd
Code
RIdifTable(df.tpsGy2, difGy2.gender)

Item 2 3 Mean location StDev MaxDiff
sdq3 -0.933 0.026 -0.454 0.678 0.960
sdq5 -0.271 0.050 -0.111 0.227 0.321
sdq6 -0.230 -0.416 -0.323 0.131 0.185
sdq7 0.283 -0.264 0.009 0.387 0.547
sdq8 -1.659 -0.625 -1.142 0.731 1.034
sdq14 0.374 0.361 0.367 0.009 0.013
sdq18 1.299 0.195 0.747 0.781 1.104
sdq19 1.625 1.163 1.394 0.327 0.462
sdq21 0.062 -0.139 -0.039 0.142 0.201
sdq22 1.299 0.654 0.977 0.456 0.645
sdq23 -0.474 -0.677 -0.576 0.143 0.203
sdq24 -0.288 0.661 0.186 0.671 0.949
sdq2_15 -1.086 -0.988 -1.037 0.069 0.098

För gy 2 går även item 7 över gränsvärdet.

10 Nästa steg

Ta bort de fem items som uppvisar DIF för kön och testa om det går att få fram en TPS där jämförbarhet är möjligt mellan årskurser och kön.

Sedan kan det ev. vara aktuellt att titta på om det går att hitta en sammansättning av items för TPS som antingen fungerar inom kön eller inom årskurs.

Code
dif.items <- c("sdq3","sdq8","sdq18","sdq22","sdq24")

df.tps.omit5 <- df.tps2 %>% 
  select(!any_of(dif.items))

10.1 DIF 2, kön + årskurs

Alla årskurser.

itemnr item
sdq5 Jag blir mycket arg och tappar ofta humöret
sdq6 Jag är ofta för mig själv. Jag gör oftast saker ensam
sdq7 Jag gör oftast som jag blir tillsagd
sdq14 Jämnåriga verkar gilla mig för det mesta
sdq19 Andra barn eller ungdomar retar eller mobbar mig
sdq21 Jag tänker mig för innan jag gör olika saker
sdq23 Jag kommer bättre överens med vuxna än med jämnåriga
Code
RIdifTable2(df.tps.omit5, dif.gender, dif.arskurs)

Item 4 5 7 8 10 11 Mean location StDev MaxDiff
sdq5 -0.257 -0.256 0.083 0.064 -0.307 0.148 -0.087 0.207 0.455
sdq6 0.020 -0.101 0.150 -0.006 -0.266 -0.296 -0.083 0.173 0.445
sdq7 0.029 0.121 -0.113 -0.063 0.248 -0.146 0.013 0.151 0.394
sdq14 0.221 0.211 0.243 0.335 0.339 0.455 0.301 0.094 0.244
sdq19 0.751 1.040 0.838 0.874 1.591 1.265 1.060 0.317 0.840
sdq21 -0.080 0.084 -0.369 -0.280 0.027 -0.024 -0.107 0.179 0.453
sdq23 0.048 -0.326 -0.151 -0.227 -0.509 -0.546 -0.285 0.225 0.594
sdq2_15 -0.732 -0.773 -0.681 -0.696 -1.123 -0.857 -0.810 0.165 0.441

19 och 23 visar fortsatt problem. Vi provar att ta bort dem.

10.2 DIF 2, kön + årskurs

Code
dif.items2 <- c("sdq3","sdq8","sdq18","sdq22","sdq24","sdq19","sdq23")

df.tps.omit5 <- df.tps2 %>% 
  select(!any_of(dif.items2))

Alla årskurser.

itemnr item
sdq5 Jag blir mycket arg och tappar ofta humöret
sdq6 Jag är ofta för mig själv. Jag gör oftast saker ensam
sdq7 Jag gör oftast som jag blir tillsagd
sdq14 Jämnåriga verkar gilla mig för det mesta
sdq21 Jag tänker mig för innan jag gör olika saker
Code
RIdifTable2(df.tps.omit5, dif.gender, dif.arskurs)

Item 4 5 6 9 10 11 Mean location StDev MaxDiff
sdq5 -0.126 -0.137 -0.127 0.203 0.175 0.273 0.043 0.193 0.409
sdq6 0.160 0.022 -0.086 0.270 0.103 -0.175 0.049 0.163 0.445
sdq7 0.164 0.242 0.432 0.001 0.044 -0.027 0.143 0.175 0.459
sdq14 0.360 0.335 0.524 0.362 0.447 0.581 0.435 0.100 0.246
sdq21 0.049 0.202 0.208 -0.263 -0.176 0.095 0.019 0.197 0.471
sdq2_15 -0.606 -0.664 -0.950 -0.573 -0.594 -0.747 -0.689 0.142 0.377

Alla items ligger ganska högt, men ingen över 0.5. Ytterligare analyser behövs för att se hur mycket det påverkar.

10.2.1 Utan åk 7

Code
df.tps.omit5$arskurs <- dif.arskurs
df.tps.omit5$gender <- dif.gender

dif.arskurs.no7 <- df.tps.omit5 %>% 
  filter(!arskurs == "Åk 7") %>% 
  pull(arskurs)
dif.gender.no7 <- df.tps.omit5 %>% 
  filter(!arskurs == "Åk 7") %>% 
  pull(gender)

df.tps.omit5 %>% 
  filter(!arskurs == "Åk 7") %>% 
  select(!arskurs) %>% 
  select(!gender) %>%
  RIdifTable2(.,dif.gender.no7,dif.arskurs.no7)

Item 3 4 6 7 Mean location StDev MaxDiff
sdq5 -0.137 -0.127 0.175 0.273 0.046 0.209 0.409
sdq6 0.022 -0.086 0.103 -0.175 -0.034 0.122 0.278
sdq7 0.242 0.432 0.044 -0.027 0.173 0.207 0.459
sdq14 0.335 0.524 0.447 0.581 0.472 0.106 0.246
sdq21 0.202 0.208 -0.176 0.095 0.082 0.180 0.384
sdq2_15 -0.664 -0.950 -0.594 -0.747 -0.738 0.154 0.356
Code
tps.items.minstaDIF <- c("sdq5","sdq6","sdq7","sdq14","sdq21","sdq2_15")

10.3 DIF-storlek, jämförelse

För att kunna jämföra effekten av DIF på estimerade mätvärden behöver vi estimera mätvärden på två olika sätt.

Vi börjar med att ta tillbaka de items som uppvisade DIF. Sedan tar vi bort åk 7 för att minimera DIF p.g.a. årskurs. Utifrån detta kan vi ta fram item-parametrar och estimera mätvärden, och sedan dela upp datasetet så pojkar och flickor kan estimeras separat. Därefter kan vi göra jämförelser.

Code
df.dif <- df.tps2

df.dif$Kön <- dif.gender
df.dif$arskurs <- dif.arskurs

df.dif <- df.dif %>% 
  filter(!arskurs == "Åk 7") %>% 
  select(!arskurs)

df.dif$ID <- seq_along(1:nrow(df.dif))

df.dif.pojkar <- df.dif %>% 
  filter(Kön == "Pojkar")

df.dif.flickor <- df.dif %>% 
  filter(Kön == "Flickor")

df.dif.id <- df.dif$ID
df.dif.pojkarID <- df.dif.pojkar$ID
df.dif.flickorID <- df.dif.flickor$ID

df.dif$ID <- NULL
df.dif.pojkar$ID <- NULL
df.dif.flickor$ID <- NULL
df.dif$Kön <- NULL
df.dif.pojkar$Kön <- NULL
df.dif.flickor$Kön <- NULL

10.4 Estimera mätvärden x3

Code
RIitemparams(df.dif,"tps2helgrupp.csv")
Threshold 1 Threshold 2 Threshold 3 Threshold 4 Item location
sdq3 -0.19 0.57 NA NA 0.19
sdq5 -0.18 1.02 NA NA 0.42
sdq6 -0.29 1.02 NA NA 0.36
sdq7 -0.73 1.81 NA NA 0.54
sdq8 -0.92 0.16 NA NA -0.38
sdq14 -0.23 1.92 NA NA 0.84
sdq18 1.01 NA NA NA 1.01
sdq19 1.65 NA NA NA 1.65
sdq21 -0.99 1.88 NA NA 0.45
sdq22 1.45 NA NA NA 1.45
sdq23 -0.76 1.01 NA NA 0.12
sdq24 0.41 0.94 NA NA 0.68
sdq2_15 -1.33 -0.88 0.37 0.5 -0.33
Code
RIitemparams(df.dif.flickor,"tps2flickor.csv")
Threshold 1 Threshold 2 Threshold 3 Threshold 4 Item location
sdq3 -0.69 0.40 NA NA -0.14
sdq5 -0.31 1.04 NA NA 0.37
sdq6 -0.20 1.14 NA NA 0.47
sdq7 -0.43 2.06 NA NA 0.81
sdq8 -1.55 -0.11 NA NA -0.83
sdq14 -0.14 1.96 NA NA 0.91
sdq18 1.70 NA NA NA 1.7
sdq19 1.89 NA NA NA 1.89
sdq21 -0.82 2.23 NA NA 0.7
sdq22 1.91 NA NA NA 1.91
sdq23 -0.65 1.12 NA NA 0.24
sdq24 -0.13 0.86 NA NA 0.36
sdq2_15 -1.38 -0.74 0.38 0.62 -0.28
Code
RIitemparams(df.dif.pojkar,"tps2pojkar.csv")
Threshold 1 Threshold 2 Threshold 3 Threshold 4 Item location
sdq3 0.24 0.99 NA NA 0.62
sdq5 -0.07 1.05 NA NA 0.49
sdq6 -0.42 0.90 NA NA 0.24
sdq7 -1.05 1.60 NA NA 0.27
sdq8 -0.53 0.66 NA NA 0.06
sdq14 -0.34 1.89 NA NA 0.77
sdq18 0.45 NA NA NA 0.45
sdq19 1.41 NA NA NA 1.41
sdq21 -1.19 1.59 NA NA 0.2
sdq22 1.04 NA NA NA 1.04
sdq23 -0.90 0.89 NA NA 0
sdq24 1.05 1.30 NA NA 1.18
sdq2_15 -1.33 -1.04 0.35 0.4 -0.41
Code
# estimate thetas for each group
df.dif$ThetasHelgrupp <- RIestThetas2(df.dif, cpu = 8)
df.dif.flickor$ThetasFlickor <- RIestThetas2(df.dif.flickor, cpu = 8)
df.dif.pojkar$ThetasPojkar <- RIestThetas2(df.dif.pojkar, cpu = 8)

# rejoin the data to enable comparisons
df.dif.flickor$ID <- df.dif.flickorID
df.dif.pojkar$ID <- df.dif.pojkarID
df.dif$ID <- df.dif.id

df.dif.pojkar <- df.dif.pojkar %>% 
  select(!starts_with("sdq"))
df.dif.flickor <- df.dif.flickor %>% 
  select(!starts_with("sdq"))

df.dif <- df.dif %>% 
  left_join(.,df.dif.flickor, by = "ID") %>% 
  left_join(.,df.dif.pojkar, by = "ID")

# create a unified variable
df.dif <- df.dif %>% 
  mutate(ThetasSeparat = coalesce(ThetasFlickor,ThetasPojkar))

df.dif$Kön <- dif.gender.no7

10.4.1 Visuell jämförelse

Code
library(ggside)
ggplot(df.dif,
       aes(x = ThetasHelgrupp, y = ThetasSeparat, color = Kön, fill = Kön)) +
  geom_point(size = 2, alpha = 0.8) + geom_smooth(method = smooth) + 
  geom_xsidedensity(aes(y = after_stat(density))) + geom_ysidedensity(aes(x = after_stat(density))) + 
  geom_xsidehistogram(aes(y = after_stat(density)), binwidth = 0.2, alpha = 0.5) + 
  geom_ysidehistogram(aes(x = after_stat(density)),
                          binwidth = 0.2, alpha = 0.5)

Code
cor.test(df.dif$ThetasHelgrupp, df.dif$ThetasSeparat, method = "pearson")

    Pearson's product-moment correlation

data:  df.dif$ThetasHelgrupp and df.dif$ThetasSeparat
t = 3733.8, df = 7770, p-value < 2.2e-16
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
 0.9997088 0.9997336
sample estimates:
      cor 
0.9997215 
Code
cor.test(df.dif$ThetasHelgrupp, df.dif$ThetasSeparat, method = "spearman")

    Spearman's rank correlation rho

data:  df.dif$ThetasHelgrupp and df.dif$ThetasSeparat
S = 437160939, p-value < 2.2e-16
alternative hypothesis: true rho is not equal to 0
sample estimates:
      rho 
0.9944128 
Code
cor.test(df.dif$ThetasHelgrupp, df.dif$ThetasSeparat, method = "kendall")

    Kendall's rank correlation tau

data:  df.dif$ThetasHelgrupp and df.dif$ThetasSeparat
z = 119.58, p-value < 2.2e-16
alternative hypothesis: true tau is not equal to 0
sample estimates:
      tau 
0.9447749 
Code
# https://rdrr.io/cran/mirt/man/poly2dich.html
# mirt::poly2dich()
# 
# library(difR)
# dichoDif()